package com.bean;

import com.apply.DefaultHandleFunction;
import com.constant.BaseConstant;
import com.enums.ConsoleFontStyleEnum;
import com.enums.PrintType;
import com.util.*;
import lombok.Data;
import org.fusesource.jansi.Ansi;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

@Data
public class FigureBean {
    private String fileName;
    private String desc;
    private List<LineMessageBean> lineMessageBeans;
    private int startSpaceNum;

    public FigureBean(String fileName, String desc, int startSpaceNum) {
        initialize(fileName, startSpaceNum);
        this.desc = desc;
    }

    public FigureBean(String fileName, int startSpaceNum) {
        this(fileName, "", startSpaceNum);
    }

    public FigureBean(String fileName) {
        this(fileName, 0);
    }

    private void initialize(String fileName, int startSpaceNum) {
        this.fileName = fileName;
        this.startSpaceNum = startSpaceNum;
        List<String> lines = ReadResourceFileUtil.readToList(fileName, StrUtil.generateSpaces(startSpaceNum));
        List<LineMessageBean> lineMessageBeanList = new ArrayList<>();
        for (String line : lines) {
            LineMessageBean lineMessageBean = new LineMessageBean();
            List<CharBean> charBeanList = new ArrayList<>();
            for (int i = 0; i < line.length(); i++) {
                char charValue = line.charAt(i);
                CharBean charBean = new CharBean();
                charBean.setCharValue(charValue);
                charBean.setColor(new CharColor());
                charBeanList.add(charBean);
            }
            lineMessageBean.setCharBeans(charBeanList);
//            lineMessageBean.setHandleFunction(new DefaultHandleFunction());
            lineMessageBeanList.add(lineMessageBean);
        }
        this.setLineMessageBeans(lineMessageBeanList);
    }

    public void printByLine(int sleepTime) {
        if (this.lineMessageBeans.get(0).getHandleFunction() == null) {
            List<String> lines = new ArrayList<>();
            for (LineMessageBean lineMessageBean : this.lineMessageBeans) {
                StringBuilder line = new StringBuilder();
                List<CharBean> charBeans = lineMessageBean.getCharBeans();
                for (CharBean charBean : charBeans) {
                    line.append(charBean.getCharValue());
                }
                lines.add(line.toString());
            }
            commonPrintByLine(lines,sleepTime);
            return;
        }
        PrintType printType = getPrintType();
        if (PrintType.CONSOLE.equals(printType)) {
            consolePrintByLine(lineMessageBeans, sleepTime);
        } else {
            terminalPrintByLine(lineMessageBeans, sleepTime);
        }
    }

    public void printByLine() {
        printByLine(BaseConstant.DEFAULT_LINE_PRINT_INTERVAL);
    }

    public void printByChar(int sleepTime) {
        if (this.lineMessageBeans.get(0).getHandleFunction() == null){
            for (LineMessageBean lineMessageBean : this.lineMessageBeans) {
                StringBuilder line = new StringBuilder();
                List<CharBean> charBeans = lineMessageBean.getCharBeans();
                for (CharBean charBean : charBeans) {
                    line.append(charBean.getCharValue());
                }
                commonPrintByChar(line.toString(),sleepTime);
            }
            return;
        }
        PrintType printType = getPrintType();
        if (PrintType.CONSOLE.equals(printType)) {
            consolePrintByChar(lineMessageBeans, sleepTime);
        } else {
            terminalPrintByChar(lineMessageBeans, sleepTime);
        }
    }

    public void printByChar() {
        printByChar(BaseConstant.DEFAULT_Char_PRINT_INTERVAL);
    }

    private void consolePrintByLine(List<LineMessageBean> lineMessageBeans, int sleepTime) {
        for (LineMessageBean lineMessageBean : lineMessageBeans) {
            lineMessageBean.getHandleFunction().handleLine(lineMessageBean.getCharBeans());
            List<CharBean> charBeans = lineMessageBean.getCharBeans();
            List<Character> characters = new ArrayList<>();
            List<FontStyleBean> fontStyleBeans = new ArrayList<>();
            for (CharBean charBean : charBeans) {
                characters.add(charBean.getCharValue());
                fontStyleBeans.add(charBean.getColor().getConsoleFontStyleBean());
            }
            char[] charArray = characters.stream()
                    .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
                    .toString()
                    .toCharArray();
            ConsolePrintColorStrUtil.printLine(charArray, fontStyleBeans);
            ThreadUtil.sleep(sleepTime);
        }
    }

    private void consolePrintByChar(List<LineMessageBean> lineMessageBeans, int sleepTime) {
        for (LineMessageBean lineMessageBean : lineMessageBeans) {
            lineMessageBean.getHandleFunction().handleLine(lineMessageBean.getCharBeans());
            List<CharBean> charBeans = lineMessageBean.getCharBeans();
            ArrayList<Character> characters = new ArrayList<>();
            List<FontStyleBean> fontStyleBeans = new ArrayList<>();
            for (CharBean charBean : charBeans) {
                characters.add(charBean.getCharValue());
                fontStyleBeans.add(charBean.getColor().getConsoleFontStyleBean());
            }
            char[] charArray = characters.stream()
                    .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
                    .toString()
                    .toCharArray();
            ConsolePrintColorStrUtil.printByChar(charArray, fontStyleBeans, sleepTime);
        }
    }

    private void terminalPrintByLine(List<LineMessageBean> lineMessageBeans, int sleepTime) {
        for (LineMessageBean lineMessageBean : lineMessageBeans) {
            lineMessageBean.getHandleFunction().handleLine(lineMessageBean.getCharBeans());
            List<CharBean> charBeans = lineMessageBean.getCharBeans();
            char[] chars = new char[charBeans.size()];
            Ansi.Color[] colors = new Ansi.Color[charBeans.size()];
            for (int i = 0; i < charBeans.size(); i++) {
                chars[i] = charBeans.get(i).getCharValue();
                colors[i] = charBeans.get(i).getColor().getTerminalColor();
            }
            TerminalPrintColorStrUtil.printByLine(chars, colors, sleepTime);
        }
    }

    private void terminalPrintByChar(List<LineMessageBean> lineMessageBeans, int sleepTime) {
        for (LineMessageBean lineMessageBean : lineMessageBeans) {
            lineMessageBean.getHandleFunction().handleLine(lineMessageBean.getCharBeans());
            List<CharBean> charBeans = lineMessageBean.getCharBeans();
            char[] chars = new char[charBeans.size()];
            Ansi.Color[] colors = new Ansi.Color[charBeans.size()];
            for (int i = 0; i < charBeans.size(); i++) {
                chars[i] = charBeans.get(i).getCharValue();
                colors[i] = charBeans.get(i).getColor().getTerminalColor();
            }
            TerminalPrintColorStrUtil.printByChar(chars, colors, sleepTime);
        }
    }

    private void commonPrintByChar(String str, int sleepTime) {
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            System.out.print(c);
            if (c == ' ') {
                continue;
            }
            ThreadUtil.sleep(sleepTime);
        }
        System.out.println();
    }

    private void commonPrintByLine(List<String> strList, int sleepTime) {
        for (String line : strList) {
            System.out.println(line);
            ThreadUtil.sleep(sleepTime);
        }
    }


    public PrintType getPrintType() {
        String printType = BaseConstant.printType;
        if (printType.equals(BaseConstant.TERMINAL)) {
            return PrintType.TERMINAL;
        } else if (printType.equals(BaseConstant.CONSOLE)) {
            return PrintType.CONSOLE;
        } else {
            throw new RuntimeException("printType is error");
        }
    }
}
